package cn.rxyb.core.calculate;

import java.math.RoundingMode;

/**
 * @author YJH
 * @version 1.0
 * @description 组合计算
 * @date 2020/6/27 14:41
 */
public class CombinationCalculate implements NumberUtil {

    private static CombinationCalculate combinationCalculate;

    private CombinationCalculate() {
    }


    public static CombinationCalculate getInstance() {
        if (null == combinationCalculate) {
            combinationCalculate = new CombinationCalculate();
        }
        return combinationCalculate;
    }

    /**
     * 提供精确的加法运算
     *
     * @param v1 数
     * @param v2 数
     * @return 和
     */
    public long add(long v1, Integer v2) {
        return add(Long.toString(v1), Integer.toString(v2)).longValue();
    }

    /**
     * 提供精确的加法运算
     *
     * @param v1 数
     * @param v2 数
     * @return 和
     */
    public long add(long v1, double v2) {
        return add(Long.toString(v1), Double.toString(v2)).longValue();
    }

    /**
     * 提供精确的加法运算
     *
     * @param v1 数
     * @param v2 数
     * @return 和
     */
    public Integer add(Integer v1, double v2) {
        return add(Integer.toString(v1), Double.toString(v2)).intValue();
    }


    /**
     * 提供精确的加法运算
     *
     * @param v1 数
     * @param v2 数
     * @return 和
     */
    public double addFloat(Integer v1, double v2) {
        return add(Integer.toString(v1), Double.toString(v2)).doubleValue();
    }

    /**
     * 提供精确的加法运算
     *
     * @param v1    数
     * @param v2    数
     * @param scale 保留多少位小数点
     * @return 默认是四舍五入计算方式
     */
    public double addFloat(Integer v1, double v2, int scale) {
        return add(Integer.toString(v1), Double.toString(v2)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供精确的加法运算
     *
     * @param v1           数
     * @param v2           数
     * @param scale        保留多少位小数点
     * @param roundingMode 保留小数点的方式
     * @return 和
     */
    public double addFloat(Integer v1, double v2, int scale, RoundingMode roundingMode) {
        return add(Integer.toString(v1), Double.toString(v2)).setScale(scale, roundingMode).doubleValue();
    }

    /**************************subtract***************************************/


    /**
     * 提供精确的减法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public long subtract(long v1, Integer v2) {
        return subtract(Long.toString(v1), Integer.toString(v2)).longValue();
    }

    /**
     * 提供精确的减法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public long subtract(long v1, double v2) {
        return subtract(Long.toString(v1), Double.toString(v2)).longValue();
    }

    /**
     * 提供精确的减法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public Integer subtract(Integer v1, double v2) {
        return subtract(Integer.toString(v1), Double.toString(v2)).intValue();
    }


    /**
     * 提供精确的减法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public double subtractFloat(Integer v1, double v2) {
        return subtract(Integer.toString(v1), Double.toString(v2)).doubleValue();
    }

    /**
     * 提供精确的减法运算
     *
     * @param v1    数
     * @param v2    数
     * @param scale 保留多少位小数点
     * @return 默认是四舍五入计算方式
     */
    public double subtractFloat(Integer v1, double v2, int scale) {
        return subtract(Integer.toString(v1), Double.toString(v2)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供精确的减法运算
     *
     * @param v1           数
     * @param v2           数
     * @param scale        保留多少位小数点
     * @param roundingMode 保留小数点的方式
     * @return
     */
    public double subtractFloat(Integer v1, double v2, int scale, RoundingMode roundingMode) {
        return subtract(Integer.toString(v1), Double.toString(v2)).setScale(scale, roundingMode).doubleValue();
    }


    /**************************multiply***************************************/


    /**
     * 提供精确的乘法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public long multiply(long v1, Integer v2) {
        return multiply(Long.toString(v1), Integer.toString(v2)).longValue();
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public long multiply(long v1, double v2) {
        return multiply(Long.toString(v1), Double.toString(v2)).longValue();
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public Integer multiply(Integer v1, double v2) {
        return multiply(Integer.toString(v1), Double.toString(v2)).intValue();
    }


    /**
     * 提供精确的乘法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public double multiplyFloat(Integer v1, double v2) {
        return multiply(Integer.toString(v1), Double.toString(v2)).doubleValue();
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1    数
     * @param v2    数
     * @param scale 保留多少位小数点
     * @return 默认是四舍五入计算方式
     */
    public double multiplyFloat(Integer v1, double v2, int scale) {
        return multiply(Integer.toString(v1), Double.toString(v2)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1           数
     * @param v2           数
     * @param scale        保留多少位小数点
     * @param roundingMode 保留小数点的方式
     * @return
     */
    public double multiplyFloat(Integer v1, double v2, int scale, RoundingMode roundingMode) {
        return multiply(Integer.toString(v1), Double.toString(v2)).setScale(scale, roundingMode).doubleValue();
    }


    /**
     * 提供精确的除法运算
     *
     * @param v1    数
     * @param v2    数
     * @param scale 保留多少位小数点
     * @return 默认是四舍五入计算方式
     */
    public double multiplyFloat(Long v1, double v2, int scale) {
        return multiply(Long.toString(v1), Double.toString(v2)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供精确的除法运算
     *
     * @param v1           数
     * @param v2           数
     * @param scale        保留多少位小数点
     * @param roundingMode 保留小数点的方式
     * @return
     */
    public double multiplyFloat(Long v1, double v2, int scale, RoundingMode roundingMode) {
        return multiply(Long.toString(v1), Double.toString(v2)).setScale(scale, roundingMode).doubleValue();
    }


    /**************************divide***************************************/


    /**
     * 提供精确的除法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public long divide(long v1, Integer v2) {
        return divide(Long.toString(v1), Integer.toString(v2)).longValue();
    }

    /**
     * 提供精确的除法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public long divide(long v1, double v2) {
        return divide(Long.toString(v1), Double.toString(v2)).longValue();
    }

    /**
     * 提供精确的除法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public Integer divide(Integer v1, double v2) {
        return divide(Integer.toString(v1), Double.toString(v2)).intValue();
    }


    /**
     * 提供精确的除法运算
     *
     * @param v1 数
     * @param v2 数
     * @return
     */
    public double divideFloat(Integer v1, double v2) {
        return divide(Integer.toString(v1), Double.toString(v2)).doubleValue();
    }

    /**
     * 提供精确的除法运算
     *
     * @param v1    数
     * @param v2    数
     * @param scale 保留多少位小数点
     * @return 默认是四舍五入计算方式
     */
    public double divideFloat(Integer v1, double v2, int scale) {
        return divide(Integer.toString(v1), Double.toString(v2)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供精确的除法运算
     *
     * @param v1           数
     * @param v2           数
     * @param scale        保留多少位小数点
     * @param roundingMode 保留小数点的方式
     * @return
     */
    public double divideFloat(Integer v1, double v2, int scale, RoundingMode roundingMode) {
        return divide(Integer.toString(v1), Double.toString(v2)).setScale(scale, roundingMode).doubleValue();
    }


    /**
     * 提供精确的除法运算
     *
     * @param v1    数
     * @param v2    数
     * @param scale 保留多少位小数点
     * @return 默认是四舍五入计算方式
     */
    public double divideFloat(Long v1, double v2, int scale) {
        return divide(Long.toString(v1), Double.toString(v2)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
    }



    /**
     * 提供精确的除法运算
     *
     * @param v1           数
     * @param v2           数
     * @param scale        保留多少位小数点
     * @param roundingMode 保留小数点的方式
     * @return
     */
    public double divideFloat(Long v1, double v2, int scale, RoundingMode roundingMode) {
        return divide(Long.toString(v1), Double.toString(v2)).setScale(scale, roundingMode).doubleValue();
    }
}
